﻿using System;
using System.Collections.Generic;
using Autofac;
using Autofac.Core;

namespace ZilLion.Service.Core.Ioc
{
    public class IocContainer
    {
        public static IContainer Container { get; private set; }

        public static void InitContainer(IContainer container)
        {
            Container = container;
        }

        #region GetInstance

        /// <summary>
        ///     获取实例 泛型方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="serviceKey"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static T Resolve<T>(string serviceKey = null,
            params Parameter[] parameters) where T : class
        {
            if (!IsRegistered(typeof(T))) return ResolveUnregistered<T>();
            return serviceKey.IsNotNullOrEmpty()
                ? Container.ResolveKeyed<T>(serviceKey, parameters)
                : Container.Resolve<T>(parameters);
        }

        /// <summary>
        ///     获取实例
        /// </summary>
        /// <param name="type"></param>
        /// <param name="serviceKey"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static object Resolve(Type type, string serviceKey = null,
            params Parameter[] parameters)
        {
            if (!IsRegistered(type)) return ResolveUnregistered(type);
            if (serviceKey.IsNotNullOrEmpty())
                Container.ResolveKeyed(serviceKey, type, parameters);
            return Container.Resolve(type, parameters);
        }

        public static object ResolveOptional(Type serviceType)
        {
            return Container.ResolveOptional(serviceType);
        }

        /// <summary>
        ///     尝试获取没有注册的实例
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private static object ResolveUnregistered(Type type)
        {
            var constructors = type.GetConstructors();
            foreach (var constructor in constructors)
                try
                {
                    var parameters = constructor.GetParameters();
                    var parameterInstances = new List<object>();
                    foreach (var parameter in parameters)
                    {
                        var service = Resolve(parameter.ParameterType, null);
                        if (service == null) throw new ArgumentException("Unkown dependency");
                        parameterInstances.Add(service);
                    }
                    return Activator.CreateInstance(type, parameterInstances.ToArray());
                }
                catch (ArgumentException)
                {
                }
            throw new ArgumentException("在所有的依赖项中，未找到合适的构造函数。");
        }

        public static T ResolveUnregistered<T>() where T : class
        {
            return ResolveUnregistered(typeof(T)) as T;
        }

        public static bool TryResolve(Type serviceType, out object instance)
        {
            return Container.TryResolve(serviceType, out instance);
        }

        private static bool IsRegistered(Type serviceType)
        {
            return Container.IsRegistered(serviceType);
        }

        #endregion
    }
}